import { 
         Component, 
         OnInit,
         ViewChild,
         ViewContainerRef,
         ComponentRef,
         ComponentFactoryResolver,
         ComponentFactory,
         EmbeddedViewRef
         } from '@angular/core';


/**在此组件中测试动态生成组件FooComponent*/
import { FooComponent } from '../foo/foo.component';



@Component({
  selector: 'app-template',
  templateUrl: './template.component.html',
  styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
   
  @ViewChild('foo',{read:ViewContainerRef})viewContainerRef:ViewContainerRef;

  constructor(private resolver:ComponentFactoryResolver) { }

  ngOnInit() {

  }

  createFoo(){
       //获取组件工厂
       let factory:ComponentFactory<FooComponent>=this.resolver.resolveComponentFactory(FooComponent);
       //利用factory动态创建组件并返回创建的组件
       let componentRef:ComponentRef<FooComponent>=this.viewContainerRef.createComponent(factory);
           //配置组件实例的输入属性(message)，订阅输出事件(ok),配置动态组件的销毁的回调函数
           componentRef.instance.message="确认删除?";
           componentRef.instance.ok.subscribe((e)=>{console.log(e);});
           componentRef.onDestroy(function(){alert('销毁Foo')}); 

       /***********
           总结
           获取装载动态组件的容器

           在组件类的构造函数中，注入 ComponentFactoryResolver 对象

           调用 ComponentFactoryResolver 对象的 resolveComponentFactory() 方法创建 ComponentFactory 对象

           调用组件容器对象的 createComponent() 方法创建组件并自动添加动态组件到组件容器中

           基于返回的 ComponentRef 组件实例，配置组件相关属性 (可选)

           在模块 Metadata 对象的 entryComponents 属性中添加动态组件

           declarations - 用于指定属于该模块的指令和管道列表

           entryComponents - 用于指定在模块定义时，需要编译的组件列表。对于列表中声明的每个组件，Angular 将会创建对应的一个 ComponentFactory 对象，并将其存储在 ComponentFactoryResolver 对象中 
       *******/
  }

  killFoo(){
   this.viewContainerRef.clear();
  }

  ngOnDestroy(){
       this.viewContainerRef.clear();
  }
  
  popModal(){
      
      //用ComponentFactoryResolver创建ComponentFactory
     let factory:ComponentFactory<FooComponent>=this.resolver.resolveComponentFactory(FooComponent);
          //用ComponentFactory直接创建Component，并返回其引用ComponentRef
         let componentRef:ComponentRef<FooComponent>=factory.create(null);
             console.log(componentRef.instance)
             componentRef.instance.message='are you kidding';
             componentRef.instance.ok.subscribe((e)=>console.log(e));
             //获取组件的探测器的引用，探测组件的变化
             componentRef.changeDetectorRef.detectChanges();
         //将ComponentRef直接插入dom节点中
         window.document.body.appendChild(componentRef.location.nativeElement);
   }


}